/*
 * @Author: Wangjun
 * @Date: 2021-07-08 14:25:38
 * @LastEditTime: 2023-03-10 19:04:25
 * @LastEditors: wangjun haodreams@163.com
 * @Description:写入redis
 * @FilePath: \xr_historyd:\go\src\gitee.com\haodreams\golib\easyredis\redis.go
 * hnxr
 */

package easyredis

import (
	"context"
	"encoding/json"
	"fmt"
	"strings"
	"time"

	"gitee.com/haodreams/libs/ee"
	"gitee.com/haodreams/golib/logs"
	"gitee.com/haodreams/libs/config"
	"github.com/redis/go-redis/v9"
)

/**
 * @description: 写入redis数据
 * @param {*}
 * @return {*}
 */
type Redis struct {
	enable bool //是否开启redis写入功能
	option redis.Options
	client *redis.Client
	ctx    context.Context
}

const maxNum = 5000

type RedisSetter interface {
	GetID() string
}

/**
 * @description: 新建一个redis
 * @param {string} prefix
 * @return {*}
 */
func NewSimpleRedis(prefix string) (r *Redis, err error) {
	r = new(Redis)
	err = r.Setup(prefix)
	return
}

/**
 * @description: web客户端的初始化
 * @param {string} prefix key的前缀
 * @return {*}
 */
func (m *Redis) Setup(prefix string) (err error) {
	m.ctx = context.Background()
	m.option.Addr = config.String(prefix + "redis_host")
	if m.option.Addr == "" {
		err = ee.NewError("无效的redis地址,关闭redis写入功能").Print(logs.CbError)
		m.enable = false
		return
	}
	m.option.Password = config.String(prefix + "redis_password")
	m.option.DB = config.DefaultInt(prefix+"redis_default_db", 6)

	addrs := strings.Split(m.option.Addr, ",")
	if len(addrs) > 1 { //连接哨兵redis(集团)
		MasterName := config.DefaultString(prefix+"redis_master_name", "redis-sentinel")
		m.client = redis.NewFailoverClient(&redis.FailoverOptions{
			MasterName:    MasterName,
			SentinelAddrs: addrs,
			Password:      m.option.Password,
			DB:            m.option.DB,
			ReadTimeout:   60 * time.Second,
			WriteTimeout:  60 * time.Second,
		})
		result, err := m.client.Ping(m.ctx).Result()
		if err != nil {
			logs.Error("ping err :", err)
			return ee.Print(err, logs.CbError)
		}
		fmt.Println(result)

	} else { //连接单机redis(区域)
		m.client = redis.NewClient(&m.option)
		if m.client == nil {
			err = ee.NewError("无效的redis客户端")
			return ee.Print(err, logs.CbError)
		}
	}

	m.enable = true
	return
}

// KV []string
func (m *Redis) hmset(key string, kvs []string) (msg string, err error) {
	now := time.Now()
	res := m.client.HMSet(m.ctx, key, kvs)
	if res.Err() != nil {
		logs.Error(res.Err())
		err = res.Err()
		return
	}
	msg = fmt.Sprint("Write to redis used time:", time.Since(now), "insert number:", len(kvs)/2)
	return
}

func (m *Redis) HGET(key, field string) (result string, err error) {
	if !m.enable {
		return
	}
	res := m.client.HGet(m.ctx, key, field)
	if res.Err() != nil {
		err = res.Err()
		return
	}

	return res.Result()
}

// HVALS
func (m *Redis) HVALS(key string) (result []string, err error) {
	if !m.enable {
		return
	}
	res := m.client.HVals(m.ctx, key)
	if res.Err() != nil {
		err = res.Err()
		return
	}

	return res.Result()
}

func (m *Redis) HMSet(key string, list []RedisSetter) (msg string, err error) {
	if !m.enable {
		return
	}
	total := 0
	now := time.Now()
	var value string
	kvs := make([]string, maxNum)
	i := 0
	for _, stateDetail := range list {
		if stateDetail == nil {
			continue
		}
		kvs[i] = stateDetail.GetID()
		i++
		data, err := json.Marshal(stateDetail)
		if err != nil {
			value = "{}"
		} else {
			value = string(data)
		}
		kvs[i] = value
		i++
		if i >= maxNum {
			m.hmset(key, kvs[:i])
			i = 0
		}
		total++

		if i >= maxNum {
			msg, err = m.hmset(key, kvs[:i])
			if err != nil {
				return msg, err
			}
			i = 0
		}
		total++
	}

	if i > 0 {
		msg, err = m.hmset(key, kvs[:i])
		if err != nil {
			return msg, err
		}
	}
	msg = fmt.Sprint("Insert to redis number:", total, " used time:", time.Since(now))
	return
}
